home *** CD-ROM | disk | FTP | other *** search
/ Amiga Inside! / Amiga FD Inside (1995)(Ultramax).iso / berndspd / devtools / intuigen / intuigenlibs / gtrequest.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-22  |  49.1 KB  |  1,991 lines

  1. /*
  2. GTRequest.c
  3.  
  4. (C) Copyright 1993 Justin Miller
  5.     This file is part of the IntuiGen package.
  6.     Use of this code is pursuant to the license outlined in
  7.     COPYRIGHT.txt, included with the IntuiGen package.
  8.  
  9.     As per COPYRIGHT.txt:
  10.  
  11.     1)  This file may be freely distributed providing that
  12.         it is unmodified, and included in a complete IntuiGen
  13.         2.0 package (it may not be distributed alone).
  14.  
  15.     2)  Programs using this code may not be distributed unless
  16.         their author has paid the Shareware fee for IntuiGen 2.0.
  17. */
  18.  
  19.  
  20. #include <stddef.h>
  21. #include <stdlib.h>
  22. #include <exec/exec.h>
  23. #include <exec/tasks.h>
  24. #include <exec/libraries.h>
  25. #include <exec/lists.h>
  26. #include <dos/dos.h>
  27. #include <dos/dosextens.h>
  28. #include <intuition/intuition.h>
  29. #include <IntuiGen/GTRequest.h>
  30. #include <devices/keymap.h>
  31. #include <devices/inputevent.h>
  32. #include <devices/console.h>
  33. #include <libraries/gadtools.h>
  34. #include <utility/tagitem.h>
  35. #include <clib/exec_protos.h>
  36. #include <clib/intuition_protos.h>
  37. #include <clib/graphics_protos.h>
  38. #include <clib/alib_protos.h>
  39. #include <clib/gadtools_protos.h>
  40. #include <clib/utility_protos.h>
  41.  
  42. struct Node *FirstItem(struct List *l)
  43. {
  44.     return l->lh_Head!=&l->lh_Tail ? l->lh_Head : 0;
  45. }
  46.  
  47. struct Node *NextItem(struct Node *n)
  48. {
  49.     return n->ln_Succ->ln_Succ ? n->ln_Succ : 0;
  50. }
  51.  
  52. struct ReqNode {
  53.     struct Node Node;
  54.     struct GTRequest *req;
  55. };
  56.  
  57. struct GTPrivate {
  58.     struct Requester *BlockReq;
  59.     struct Gadget *Context;
  60.     struct VisualInfo *vinfo;
  61.     struct Window *OpenedWindow;
  62.     struct Menu *MenuStrip;
  63.     SHORT Blocked;
  64.     SHORT YOffSet;
  65.     struct IntuiMessage LastGadgetEvent,BeforeLastGadgetEvent;
  66. };
  67.  
  68. __far int cismember (char c,char *set)
  69. /* returns true if c is in set */
  70. {
  71.     short i;
  72.     for (i=0;set[i];++i)
  73.     if (set[i]==c) return (++i);
  74.     return (0);
  75. }
  76.  
  77. __far void delchars (char *s,USHORT p,USHORT n)
  78. /* deletes n chars starting at position p from string s */
  79. {
  80.     n+=p;
  81.     if (n>strlen(s)) n=strlen(s);
  82.     do {
  83.     s[p++]=s[n];
  84.     } while (s[n++]);
  85. }
  86.  
  87. __far BOOL strelim (char *s,char *elim,BOOL k)
  88. /* when k is true, only chars in elim allowed, otherwise,
  89.  * only chars not in elim allowed */
  90. {
  91.     SHORT i=-1;
  92.     BOOL f=0;
  93.  
  94.     while (s[++i])
  95.     if ((cismember(s[i],elim) && !k)||(!cismember(s[i],elim) && k)) {
  96.         f=1;
  97.         delchars (s,i--,1);
  98.     }
  99.     return (f);
  100. }
  101.  
  102.  
  103. __far void EndGTRequest(struct GTRequest *req,LONG terminate,
  104.            struct MessageHandler *mh,struct GTControl *gtc)
  105. {
  106.     req->Terminate=terminate;
  107.     req->EndMsgHandler=mh;
  108.     req->EndControl=gtc;
  109. }
  110.  
  111. __far struct GTControl *AllocGTControl(struct GTRequest *req,ULONG AdditionalBytes)
  112. {
  113.     struct GTControl *k;
  114.  
  115.     k=AllocRemember(&req->GTKey,sizeof(struct GTControl)+AdditionalBytes,MEMF_PUBLIC | MEMF_CLEAR);
  116.     return k;
  117. }
  118.  
  119. __far SHORT ASCIIToRawKey (char c);
  120. __far void BindClassToMsgHandler(struct GTRequest *req,struct MessageHandler *mh);
  121.  
  122. __far void AddInternalControl(struct GTRequest *req,struct GTControl *parent,struct GTControl *gtc,ULONG type)
  123. {
  124.     struct GTControl *c;
  125.     struct MessageHandler *mh;
  126.  
  127.     gtc->Flags|=type;
  128.     if (!(gtc->Flags & GTC_GOTRAWKEY) && gtc->ASCIICommand) {
  129.     gtc->RawKeyCommand=ASCIIToRawKey(gtc->ASCIICommand);
  130.     gtc->Flags |= GTC_GOTRAWKEY;
  131.     }
  132.     for (mh=gtc->MsgHandlerList;mh;mh=mh->Next)
  133.      BindClassToMsgHandler(req,mh);
  134.  
  135.     gtc->Next=parent->Next;
  136.     parent->Next=gtc;
  137. }
  138.  
  139. __far struct NewGadget *AllocNewGadget(struct GTRequest *req,struct NewGadget *sg,
  140.                         LONG x,LONG y,LONG w,LONG h)
  141. {
  142.     struct NewGadget *ng=0;
  143.  
  144.     if (ng=AllocRemember(&req->GTKey,sizeof(*ng),MEMF_PUBLIC | MEMF_CLEAR)) {
  145.     /* if (sg) *ng=*sg; */
  146.  
  147.     ng->ng_GadgetText=sg->ng_GadgetText;
  148.     ng->ng_TextAttr=sg->ng_TextAttr;
  149.     ng->ng_GadgetID=sg->ng_GadgetID;
  150.     ng->ng_Flags=sg->ng_Flags;
  151.  
  152.     ng->ng_LeftEdge=x;
  153.     ng->ng_TopEdge=y;
  154.     ng->ng_Width=w;
  155.     ng->ng_Height=h;
  156.     }
  157.     return ng;
  158. }
  159.  
  160. __far void SendMessageToControl(struct GTRequest *req,struct GTControl *gtc,struct IntuiMessage *msg,
  161.                 UBYTE *class)
  162. {
  163.     struct MessageHandler *mh;
  164.  
  165.     for (mh=gtc->MsgHandlerList;mh;mh=mh->Next)
  166.     if (mh->Name && !strcmp(class,mh->Name)) break;
  167.  
  168.     if (mh && mh->HandlerFunction)
  169.     (*(mh->HandlerFunction)) (req,msg,gtc,mh);
  170. }
  171.  
  172. __far void SetControlAttrsA (struct GTRequest *req,struct GTControl *gtc,struct TagItem *ti)
  173. {
  174.     struct TagItem *tia;
  175.  
  176.     if (tia=FindTagItem(gtc->AttributeTag,ti)) {
  177.     gtc->Attribute=tia->ti_Data;
  178.     }
  179.  
  180.     if (gtc->SetAttrs) (*(gtc->SetAttrs)) (req,gtc,ti);
  181.     else GT_SetGadgetAttrsA(gtc->Gadget,req->Window,0,ti);
  182. }
  183.  
  184. __far void SetControlAttrs(struct GTRequest *req,struct GTControl *gtc,Tag tag1,...)
  185. {
  186.     SetControlAttrsA(req,gtc,&tag1);
  187. }
  188.  
  189. /* Generates the necessary structures and SHORT values for a two pixel thick,
  190.  * two color box.  Returns pointer to first of two Border structures.  All
  191.  * information is allocated on the Remember key
  192. */
  193. __far struct Border *MakeBox (USHORT w,USHORT h,UBYTE c1,UBYTE c2,struct Remember **key)
  194. {
  195.     struct Border *b,*d;
  196.     SHORT *f,*j;
  197.  
  198.     b=(struct Border *)AllocRemember (key,sizeof(struct Border)*2,MEMF_PUBLIC | MEMF_CLEAR);
  199.     if (!b) return (0);
  200.     f=(SHORT *)AllocRemember (key,48,MEMF_PUBLIC | MEMF_CLEAR);
  201.     if (!f) return (0);
  202.     d=&b[1];
  203.     j=&f[12];
  204.  
  205.     b->DrawMode=JAM1;
  206.     b->Count=6;
  207.     *d=*b;
  208.  
  209.     b->XY=f;
  210.     d->XY=j;
  211.     d->FrontPen=c2;
  212.     b->FrontPen=c1;
  213.     b->NextBorder=d;
  214.  
  215.     f[1]=j[3]=j[5]=h;
  216.     f[4]=j[0]=j[2]=w;
  217.     f[7]=f[8]=f[9]=f[10]=j[6]=j[11]=1;
  218.     f[6]=j[8]=j[10]=w-1;
  219.     f[11]=j[7]=j[9]=h-1;
  220.  
  221.     return (b);
  222. }
  223.  
  224. /************************************************************************/
  225. /* Functions to implement ToggleSelect pseudokind            */
  226. /************************************************************************/
  227.  
  228. __far void ToggleGUp (struct GTRequest *req,struct GTControl *gtc,
  229.          struct IntuiMessage *msg)
  230. {
  231.     gtc->Attribute=gtc->Gadget->Flags & GFLG_SELECTED ? 1 : 0;
  232. }
  233.  
  234. __far void ToggleSetAttrs (struct GTRequest *req,struct GTControl *gtc,
  235.               struct TagItem *ti)
  236. {
  237.     ULONG onoff;
  238.  
  239.     onoff=GetTagData(GTCT_TOGGLED,0xffffffff,ti);
  240.     if (onoff!=0xffffffff) {
  241.     ULONG isonoff;
  242.  
  243.     onoff = onoff ? 1 : 0;
  244.  
  245.     isonoff=gtc->Gadget->Flags & GFLG_SELECTED ? 1 : 0;
  246.     if (onoff!=isonoff) {
  247.         gtc->Gadget->Flags^=GFLG_SELECTED;
  248.         RefreshGList(gtc->Gadget,req->Window,0,1);
  249.     }
  250.     }
  251.     GT_SetGadgetAttrsA(gtc->Gadget,req->Window,0,ti);
  252. }
  253.  
  254. __far struct Gadget *CreateToggleSelectKind(struct GTPKind *kclass,struct Gadget *gad,
  255.                   struct GTControl *gtc,struct GTRequest *req,
  256.                   struct VisualInfo *vinfo)
  257. {
  258.     ULONG onoff;
  259.  
  260.     gtc->NewGadget->ng_VisualInfo=vinfo;
  261.     gad=CreateGadgetA(BUTTON_KIND,gad,gtc->NewGadget,gtc->GadgetTags);
  262.     if (gad) {
  263.     gad->Activation|=GACT_TOGGLESELECT;
  264.     if (!(gtc->GUpUpdateControl)) gtc->GUpUpdateControl=ToggleGUp;
  265.     gtc->SetAttrs=ToggleSetAttrs;
  266.     }
  267.  
  268.     onoff=GetTagData(GTCT_TOGGLED,0xffffffff,gtc->GadgetTags);
  269.     if (onoff!=0xffffffff && onoff!=0) SetControlAttrs(req,gtc,GTCT_TOGGLED,onoff,TAG_DONE);
  270.     return gad;
  271. }
  272.  
  273. /***************************************************************************/
  274. /*               These are for ImageButton PKind               */
  275. /***************************************************************************/
  276.  
  277. __far void ImageButtonSetAttrs (struct GTRequest *req,struct GTControl *gtc,
  278.               struct TagItem *ti)
  279. {
  280.     ULONG onoff,toggle;
  281.  
  282.     toggle=GetTagData(GTPK_Toggleselect,0,gtc->GadgetTags);
  283.     if (toggle) {
  284.     onoff=GetTagData(GTPK_Toggled,0xffffffff,ti);
  285.     if (onoff!=0xffffffff) {
  286.         ULONG isonoff;
  287.  
  288.         onoff = onoff ? 1 : 0;
  289.  
  290.         isonoff=gtc->Gadget->Flags & GFLG_SELECTED ? 1 : 0;
  291.         if (onoff!=isonoff) {
  292.         gtc->Gadget->Flags^=GFLG_SELECTED;
  293.         RefreshGList(gtc->Gadget,req->Window,0,1);
  294.         }
  295.     }
  296.     }
  297. }
  298.  
  299. __far struct Gadget *CreateImageButtonKind(struct GTPKind *kclass, struct Gadget *gad,
  300.                     struct GTControl *gtc, struct GTRequest *req,
  301.                     struct VisualInfo *vinfo)
  302. {
  303.     struct Gadget *g;
  304.     struct Image *i,*s;
  305.     ULONG toggled,toggle;
  306.  
  307.     i=GetTagData(GTPK_Image,0,gtc->GadgetTags);
  308.     s=GetTagData(GTPK_SelectedImage,0,gtc->GadgetTags);
  309.     toggle=GetTagData(GTPK_Toggleselect,0,gtc->GadgetTags);
  310.     toggled=GetTagData(GTPK_Toggled,0,gtc->GadgetTags);
  311.  
  312.     if (g=AllocRemember(&req->GTKey,sizeof(*g),MEMF_PUBLIC | MEMF_CLEAR)) {
  313.     gad->NextGadget=g;
  314.  
  315.     g->LeftEdge=gtc->NewGadget->ng_LeftEdge;
  316.     g->TopEdge=gtc->NewGadget->ng_TopEdge;
  317.     g->Width=gtc->NewGadget->ng_Width;
  318.     g->Height=gtc->NewGadget->ng_Height;
  319.  
  320.     g->Flags= s ? GFLG_GADGIMAGE | GFLG_GADGHIMAGE :
  321.         GFLG_GADGIMAGE | GFLG_GADGHCOMP;
  322.     g->Activation = toggle ? GACT_RELVERIFY | GACT_TOGGLESELECT :
  323.         GACT_RELVERIFY;
  324.     g->GadgetType=BOOLGADGET;
  325.     g->GadgetRender=i;
  326.     g->SelectRender=s;
  327.  
  328.     g->GadgetID=gtc->NewGadget->ng_GadgetID;
  329.     g->UserData=gtc->NewGadget->ng_UserData;
  330.  
  331.     if (toggle && toggled) g->Flags |= GFLG_SELECTED;
  332.  
  333.     if (!(gtc->GUpUpdateControl) && toggle)
  334.         gtc->GUpUpdateControl=ToggleGUp;
  335.  
  336.     gtc->SetAttrs=ImageButtonSetAttrs;
  337.     gtc->Gadget=g;
  338.     }
  339.     return g;
  340. }
  341.  
  342.  
  343.  
  344. struct GTPKind GlobalPKindClassList[]={
  345.     { "ToggleSelect",CreateToggleSelectKind,0 },
  346.     { "ImageButton",CreateImageButtonKind, 0 },
  347.     { 0, 0, 0 }
  348. };
  349.  
  350. /***********************************************************/
  351. /*  These Keep GTControl->Attribute current on Gadgetup    */
  352. /*  or Gadget Down.  Called by DispatchDefSetControlAttr.  */
  353. /*  Can be overriden in the GTControl structure.       */
  354. /***********************************************************/
  355.  
  356. __far void CheckBoxGUp(struct GTRequest *req,struct GTControl *gtc,
  357.          struct IntuiMessage *msg)
  358. {
  359.     gtc->Attribute=gtc->Gadget->Flags & GFLG_SELECTED;
  360. }
  361.  
  362. __far void MXGDown (struct GTRequest *req,struct GTControl *gtc,
  363.          struct IntuiMessage *msg)
  364. {
  365.     gtc->Attribute=msg->Code;
  366. }
  367.  
  368. __far void CycleGUp(struct GTRequest *req,struct GTControl *gtc,
  369.          struct IntuiMessage *msg)
  370. {
  371.     gtc->Attribute=msg->Code;
  372. }
  373.  
  374. __far void SliderGUp(struct GTRequest *req,struct GTControl *gtc,
  375.          struct IntuiMessage *msg)
  376. {
  377.     gtc->Attribute=msg->Code;
  378. }
  379.  
  380. __far void ScrollerGUp(struct GTRequest *req,struct GTControl *gtc,
  381.          struct IntuiMessage *msg)
  382. {
  383.     gtc->Attribute=msg->Code;
  384. }
  385.  
  386. __far void ListViewGUp(struct GTRequest *req,struct GTControl *gtc,
  387.          struct IntuiMessage *msg)
  388. {
  389.     gtc->Attribute=msg->Code;
  390. }
  391.  
  392. struct DefControlAttrUpdater {
  393.     ULONG Kind;
  394.     void (*GadgetUp) (struct GTRequest *,struct GTControl *,
  395.             struct IntuiMessage *);
  396.     void (*GadgetDown) (struct GTRequest *,struct GTControl *,
  397.             struct IntuiMessage *);
  398. };
  399.  
  400. struct DefControlAttrUpdater DefControlAttrUpdaters[] = {
  401.     { CHECKBOX_KIND,       CheckBoxGUp,  0 },
  402.     { MX_KIND,           0,         MXGDown },
  403.     { CYCLE_KIND,       CycleGUp,     0 },
  404.     { SLIDER_KIND,       SliderGUp,     0 },
  405.     { SCROLLER_KIND,       ScrollerGUp,  0 },
  406.     { LISTVIEW_KIND,       ListViewGUp,  0 },
  407.     { 0,           0,         0 }
  408. };
  409.  
  410. __far void DispatchDefSetControlAttr(struct GTRequest *req,struct GTControl *gtc,
  411.                 struct IntuiMessage *msg)
  412. {
  413.     USHORT i;
  414.  
  415.     for (i=0;DefControlAttrUpdaters[i].Kind;++i) {
  416.     if (gtc->Kind==DefControlAttrUpdaters[i].Kind) {
  417.         if (msg->Class == IDCMP_GADGETUP &&
  418.         DefControlAttrUpdaters[i].GadgetUp)
  419.             (*(DefControlAttrUpdaters[i].GadgetUp)) (req,gtc,msg);
  420.         else if (DefControlAttrUpdaters[i].GadgetDown)
  421.             (*(DefControlAttrUpdaters[i].GadgetDown)) (req,gtc,msg);
  422.         break;
  423.     }
  424.     }
  425. }
  426.  
  427. /***********************************************************/
  428.  
  429. __far struct GTControl *FindGadgetControl(struct GTControl *gtc,struct Gadget *g)
  430. {
  431.     while (gtc && gtc->Gadget!=g) gtc=gtc->Next;
  432.     return gtc;
  433. }
  434.  
  435. /***********************************************************/
  436. /*  Message Classes for Global Class List.  Determine if a */
  437. /*  message is of a particular type, and if it affects       */
  438. /*  given control (note that some messages will "affect"   */
  439. /*  all controls (MOUSEBUTTONS, DISKINSERTED, etc.)        */
  440. /*  If that control has a message handler the given       */
  441. /*  message it will hear about them.               */
  442. /***********************************************************/
  443.  
  444. __far BOOL IsGadgetUp(struct GTRequest *req,struct IntuiMessage *msg,
  445.         struct GTControl *gtc,struct MessageHandler *mh)
  446. {
  447.     if (msg->Class==IDCMP_GADGETUP) {
  448.     if (gtc) {
  449.         struct GTControl *cgtc;
  450.  
  451.         cgtc=FindGadgetControl(req->Controls,msg->IAddress);
  452.         if (cgtc==gtc) return 1;
  453.     } else return 1;
  454.     }
  455.     return 0;
  456. }
  457.  
  458. __far BOOL IsGadgetDown(struct GTRequest *req,struct IntuiMessage *msg,
  459.         struct GTControl *gtc,struct MessageHandler *mh)
  460. {
  461.     if (msg->Class & IDCMP_GADGETDOWN) {
  462.     if (gtc) {
  463.         struct GTControl *cgtc;
  464.  
  465.         cgtc=FindGadgetControl(req->Controls,msg->IAddress);
  466.         if (cgtc==gtc) return 1;
  467.     } else return 1;
  468.     }
  469.     return 0;
  470. }
  471.  
  472. __far BOOL IsStringDSelected(struct GTRequest *req,struct IntuiMessage *msg,
  473.             struct GTControl *gtc,struct MessageHandler *mh)
  474. {
  475.     if (IsGadgetDown(req,req->LastGadgetEvent,gtc,mh)) {
  476.     struct Gadget *g;
  477.     g=req->LastGadgetEvent->IAddress;
  478.     if ((g->GadgetType & GTYP_GTYPEMASK)==GTYP_STRGADGET) return 1;
  479.     }
  480.  
  481.     return 0;
  482. }
  483.  
  484. __far void SetStringControl (struct GTRequest *req,struct GTControl *gtc,UBYTE *string);
  485.  
  486. __far BOOL LimitStringContents(struct GTRequest *req,struct IntuiMessage *msg,
  487.                 struct GTControl *gtc,struct MessageHandler *mh)
  488. {
  489.     ULONG retval=0;
  490.  
  491.     if (gtc && IsStringDSelected(req,msg,gtc,mh)) {
  492.     UBYTE *s,*nogood,*x;
  493.     struct StringInfo *buf;
  494.     buf=(struct StringInfo *)gtc->Gadget->SpecialInfo;
  495.     if (buf) {
  496.         x=buf->Buffer;
  497.         if (gtc->ControlTags) nogood=(UBYTE *)GetTagData(GTCT_STRING_INVALIDCHARS,0,gtc->ControlTags);
  498.         if (nogood) {
  499.         s=AllocVec(strlen(x)+1,MEMF_PUBLIC);
  500.         strcpy(s,x);
  501.         if (strelim(s,nogood,0)) { SetStringControl(req,gtc,s); retval=1; }
  502.         FreeVec(s);
  503.         }
  504.     }
  505.     }
  506.     return retval;
  507. }
  508.  
  509.  
  510. __far void SetIntControl (struct GTRequest *req,struct GTControl *gtc,LONG number);
  511.  
  512. __far BOOL VerifyIntLimits(struct GTRequest *req,struct IntuiMessage *msg,
  513.             struct GTControl *gtc,struct MessageHandler *mh)
  514. {
  515.     ULONG retval=0;
  516.     if (gtc && IsStringDSelected(req,msg,gtc,mh)) {
  517.     LONG min,max,x;
  518.     UBYTE *s;
  519.     struct StringInfo *sinfo;
  520.  
  521.     sinfo=(struct StringInfo *)gtc->Gadget->SpecialInfo;
  522.     if (sinfo) {
  523.         x=atol(sinfo->Buffer);
  524.         if (gtc->ControlTags) {
  525.         min=GetTagData(GTCT_INT_MIN,0x3f47d8a3,gtc->ControlTags);
  526.         max=GetTagData(GTCT_INT_MAX,0x3f47d8a3,gtc->ControlTags);
  527.         if (min!=0x3f47d8a3 && x<min) { SetIntControl(req,gtc,min); retval=1; }
  528.         else if (max!=0x3f47d8a3 && x>max) { SetIntControl(req,gtc,max); retval=1; }
  529.         }
  530.     }
  531.     }
  532.     return retval;
  533. }
  534.  
  535. __far BOOL EndFillGadgetUp(struct GTRequest *req,struct IntuiMessage *msg,
  536.          struct GTControl *gtc,struct MessageHandler *mh)
  537. {
  538.     if (IsGadgetUp(req,msg,gtc,mh)) {
  539.     EndGTRequest(req,1,mh,gtc);
  540.     return 1;
  541.     }
  542.     return 0;
  543.  
  544. }
  545.  
  546. __far BOOL EndGadgetUp(struct GTRequest *req,struct IntuiMessage *msg,
  547.          struct GTControl *gtc,struct MessageHandler *mh)
  548. {
  549.     if (IsGadgetUp(req,msg,gtc,mh)) {
  550.     EndGTRequest(req,-1,mh,gtc);
  551.     return 1;
  552.     }
  553.     return 0;
  554. }
  555.  
  556. __far BOOL IsMouseButtons(struct GTRequest *req,struct IntuiMessage *msg,
  557.             struct GTControl *gtc,struct MessageHandler *mh)
  558. {
  559.     if (!gtc || gtc==req->ActiveControl)
  560.     if (msg->Class & IDCMP_MOUSEBUTTONS) return 1;
  561.     return 0;
  562. }
  563.  
  564. __far BOOL IsMouseMove(struct GTRequest *req,struct IntuiMessage *msg,
  565.             struct GTControl *gtc,struct MessageHandler *mh)
  566. {
  567.     if (!gtc || gtc==req->ActiveControl)
  568.     if (msg->Class & IDCMP_MOUSEMOVE) return 1;
  569.     return 0;
  570. }
  571.  
  572. __far BOOL IsDeltaMove(struct GTRequest *req,struct IntuiMessage *msg,
  573.             struct GTControl *gtc,struct MessageHandler *mh)
  574. {
  575.     if (!gtc || gtc==req->ActiveControl)
  576.     if (msg->Class & IDCMP_DELTAMOVE) return 1;
  577.     return 0;
  578. }
  579.  
  580. __far BOOL IsRawKey(struct GTRequest *req,struct IntuiMessage *msg,
  581.             struct GTControl *gtc,struct MessageHandler *mh)
  582. {
  583.     if (!gtc || gtc==req->ActiveControl)
  584.     if (msg->Class & IDCMP_RAWKEY) return 1;
  585.     return 0;
  586. }
  587.  
  588. __far BOOL IsIntuiTicks(struct GTRequest *req,struct IntuiMessage *msg,
  589.             struct GTControl *gtc,struct MessageHandler *mh)
  590. {
  591.     if (!gtc || gtc==req->ActiveControl)
  592.     if (msg->Class & IDCMP_INTUITICKS) return 1;
  593.     return 0;
  594. }
  595.  
  596. __far BOOL IsDiskInserted(struct GTRequest *req,struct IntuiMessage *msg,
  597.             struct GTControl *gtc,struct MessageHandler *mh)
  598. {
  599.     if (msg->Class & IDCMP_DISKINSERTED) return 1;
  600.     return 0;
  601. }
  602.  
  603. __far BOOL IsDiskRemoved(struct GTRequest *req,struct IntuiMessage *msg,
  604.             struct GTControl *gtc,struct MessageHandler *mh)
  605. {
  606.     if (msg->Class & IDCMP_DISKREMOVED) return 1;
  607.     return 0;
  608. }
  609.  
  610. __far BOOL IsMenuVerify(struct GTRequest *req,struct IntuiMessage *msg,
  611.             struct GTControl *gtc,struct MessageHandler *mh)
  612. {
  613.     if (msg->Class & IDCMP_MENUVERIFY) return 1;
  614.     return 0;
  615. }
  616.  
  617. __far BOOL IsMenuPick(struct GTRequest *req,struct IntuiMessage *msg,
  618.             struct GTControl *gtc,struct MessageHandler *mh)
  619. {
  620.     if (msg->Class & IDCMP_MENUPICK) return 1;
  621.     return 0;
  622. }
  623.  
  624. __far BOOL IsSizeVerify(struct GTRequest *req,struct IntuiMessage *msg,
  625.             struct GTControl *gtc,struct MessageHandler *mh)
  626. {
  627.     if (msg->Class & IDCMP_SIZEVERIFY) return 1;
  628.     return 0;
  629. }
  630.  
  631. __far BOOL IsNewSize(struct GTRequest *req,struct IntuiMessage *msg,
  632.             struct GTControl *gtc,struct MessageHandler *mh)
  633. {
  634.     if (msg->Class & IDCMP_NEWSIZE) return 1;
  635.     return 0;
  636. }
  637.  
  638. __far BOOL IsReqVerify(struct GTRequest *req,struct IntuiMessage *msg,
  639.             struct GTControl *gtc,struct MessageHandler *mh)
  640. {
  641.     if (msg->Class & IDCMP_REQVERIFY) return 1;
  642.     return 0;
  643. }
  644.  
  645. __far BOOL IsReqSet(struct GTRequest *req,struct IntuiMessage *msg,
  646.             struct GTControl *gtc,struct MessageHandler *mh)
  647. {
  648.     if (msg->Class & IDCMP_REQSET) return 1;
  649.     return 0;
  650. }
  651.  
  652. __far BOOL IsReqClear(struct GTRequest *req,struct IntuiMessage *msg,
  653.             struct GTControl *gtc,struct MessageHandler *mh)
  654. {
  655.     if (msg->Class & IDCMP_REQCLEAR) return 1;
  656.     return 0;
  657. }
  658.  
  659. __far BOOL IsActiveWindow(struct GTRequest *req,struct IntuiMessage *msg,
  660.             struct GTControl *gtc,struct MessageHandler *mh)
  661. {
  662.     if (msg->Class & IDCMP_ACTIVEWINDOW) return 1;
  663.     return 0;
  664. }
  665.  
  666. __far BOOL IsInactiveWindow(struct GTRequest *req,struct IntuiMessage *msg,
  667.             struct GTControl *gtc,struct MessageHandler *mh)
  668. {
  669.     if (msg->Class & IDCMP_INACTIVEWINDOW) return 1;
  670.     return 0;
  671. }
  672.  
  673. __far BOOL IsRefreshWindow(struct GTRequest *req,struct IntuiMessage *msg,
  674.             struct GTControl *gtc,struct MessageHandler *mh)
  675. {
  676.     if (msg->Class & IDCMP_REFRESHWINDOW) return 1;
  677.     return 0;
  678. }
  679.  
  680. __far BOOL IsNewPrefs(struct GTRequest *req,struct IntuiMessage *msg,
  681.             struct GTControl *gtc,struct MessageHandler *mh)
  682. {
  683.     if (msg->Class & IDCMP_NEWPREFS) return 1;
  684.     return 0;
  685. }
  686.  
  687. __far BOOL IsCloseWindow(struct GTRequest *req,struct IntuiMessage *msg,
  688.             struct GTControl *gtc,struct MessageHandler *mh)
  689. {
  690.     if (msg->Class & IDCMP_CLOSEWINDOW) return 1;
  691.     return 0;
  692. }
  693.  
  694.  
  695. struct MessageClass GlobalMsgClassList[]={
  696.     { "GadgetUp",IsGadgetUp },
  697.     { "GadgetDown",IsGadgetDown },
  698.     { "MouseButtons",IsMouseButtons },
  699.     { "MouseMove",IsMouseMove },
  700.     { "DeltaMove",IsDeltaMove },
  701.     { "RawKey",IsRawKey },
  702.     { "IntuiTicks",IsIntuiTicks },
  703.     { "DiskInserted",IsDiskInserted },
  704.     { "DiskRemoved",IsDiskRemoved },
  705.     { "MenuVerify",IsMenuVerify },
  706.     { "MenuPick",IsMenuPick },
  707.     { "SizeVerify",IsSizeVerify },
  708.     { "NewSize",IsNewSize },
  709.     { "ReqVerify",IsReqVerify },
  710.     { "ReqSet",IsReqSet },
  711.     { "ReqClear",IsReqClear },
  712.     { "ActiveWindow",IsActiveWindow },
  713.     { "InactiveWindow",IsInactiveWindow },
  714.     { "RefreshWindow",IsRefreshWindow },
  715.     { "NewPrefs",IsNewPrefs },
  716.     { "CloseWindow",IsCloseWindow },
  717.     { "EndGadgetUp",EndGadgetUp },
  718.     { "EndFillGadgetUp",EndFillGadgetUp },
  719.     { "LimitStringContents",LimitStringContents },
  720.     { "VerifyIntLimits",VerifyIntLimits },
  721.     { "StringDSelected",IsStringDSelected },
  722.     {  0, 0 }
  723. };
  724.  
  725. /***********************************************************/
  726. /* The following routines handle conversion between RAWKEY */
  727. /* and ASCII based on the current Keymap.           */
  728. /***********************************************************/
  729.  
  730. __far UBYTE InterpretDKey(UBYTE *start,UBYTE *descrip)
  731. {
  732.     if (*descrip & DPF_DEAD) return(0);
  733.     if (*descrip==0) { ++descrip; return(*descrip); }
  734.     if (*descrip & DPF_MOD) {
  735.     ++descrip;
  736.     descrip=start + *descrip;
  737.     return (*descrip);
  738.     }
  739.     return (0);
  740. }
  741.  
  742.  
  743.  
  744. /* Takes RAWKEY code and qualifier (from an IntuiMessage) and returns
  745.    ASCII equivalent
  746. */
  747.  
  748. __far UBYTE RawKeyToAscii (USHORT code,USHORT qual)
  749. {
  750.     UBYTE key=0;
  751.     USHORT r;
  752.     struct MsgPort *port=0;
  753.     struct IOStdReq *req=0;
  754.     struct KeyMap *km=0;
  755.     ULONG *kmentry;
  756.     UBYTE *kmflags;
  757.     UBYTE *kmdkey,*kmdstart;
  758.     UBYTE *kmcaps;
  759.  
  760.     if (code>0x67) return (0);
  761.  
  762.     port=CreatePort(0,0);
  763.     if (!port) goto error;
  764.     req=CreateStdIO(port);
  765.     if (!req) goto error;
  766.  
  767.     km=AllocMem(sizeof(struct KeyMap),MEMF_PUBLIC | MEMF_CLEAR);
  768.     if (!km) goto error;
  769.  
  770.     if (OpenDevice("console.device",-1,req,0)) goto error;
  771.     req->io_Command=CD_ASKDEFAULTKEYMAP;
  772.     req->io_Length=sizeof(struct KeyMap);
  773.     req->io_Data=km;
  774.     DoIO(req);
  775.     if (req->io_Error) { CloseDevice(req); goto error; }
  776.  
  777.     if (code>0x3f) {
  778.     kmflags=km->km_HiKeyMapTypes;
  779.     kmentry=km->km_HiKeyMap;
  780.     kmcaps=km->km_HiCapsable;
  781.     } else {
  782.     kmflags=km->km_LoKeyMapTypes;
  783.     kmentry=km->km_LoKeyMap;
  784.     kmcaps=km->km_LoCapsable;
  785.     }
  786.  
  787.     if (code>0x3f) code-=0x40;
  788.  
  789.     if (qual & IEQUALIFIER_CAPSLOCK) {
  790.     UBYTE byt,bit;
  791.     byt=code/8;
  792.     bit=code%8;
  793.     if (kmcaps[byt] & bit) qual|=IEQUALIFIER_LSHIFT;
  794.     }
  795.  
  796.     if (kmflags[code] & KCF_STRING) { CloseDevice(req); goto error; }
  797.     if (kmflags[code] & KCF_DEAD) {
  798.  
  799.     kmdkey=kmdstart=(UBYTE *)kmentry[code];
  800.  
  801.     if ( ( qual & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT) ) && (kmflags[code] & KCF_SHIFT) ) {
  802.         kmdkey+=2;
  803.         if ( ( qual & (IEQUALIFIER_LALT | IEQUALIFIER_RALT) ) && (kmflags[code] & KCF_ALT) ) {
  804.         kmdkey+=4;
  805.         key=InterpretDKey(kmdstart,kmdkey);
  806.         } else key=InterpretDKey(kmdstart,kmdkey);
  807.     } else if ( ( qual & (IEQUALIFIER_LALT | IEQUALIFIER_RALT) ) && (kmflags[code] & KCF_ALT) ) {
  808.         kmdkey+=4;
  809.         key=InterpretDKey(kmdstart,kmdkey);
  810.     } else { key=InterpretDKey(kmdstart,kmdkey); }
  811.  
  812.     } else {
  813.     if (qual & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) {
  814.         if (qual & (IEQUALIFIER_LALT | IEQUALIFIER_RALT)) {
  815.         key=(kmentry[code] & 0xff000000) >> 24;
  816.         } else key=(kmentry[code] & 0xff00) >> 8;
  817.     } else if (qual & (IEQUALIFIER_LALT | IEQUALIFIER_RALT))
  818.         key=(kmentry[code] & 0xff0000) >> 16;
  819.     else { key=kmentry[code] & 0xff; }
  820.     }
  821.  
  822.     if (qual & IEQUALIFIER_CONTROL) key&=159;
  823.  
  824.     CloseDevice(req);
  825. error: if (req) DeleteStdIO (req);
  826.        if (port) DeletePort (port);
  827.        if (km) FreeMem(km,sizeof (struct KeyMap));
  828.        return (key);
  829. }
  830.  
  831.  
  832. /* Takes ASCII char and returns Rawkey code.  ASCII code must correspond to
  833.    letter painted on keyboard keycap (the unqualified value).  Qualifier
  834.    must be determined as follows (Under IGRequest which does not
  835.    differentiate between right and left):
  836.  
  837.     SHIFT =  1
  838.     ALT   = 16
  839.     CTRL  =  8
  840.     AMIGA = 64
  841.  
  842.    Returns -1 error.
  843. */
  844.  
  845. __far SHORT ASCIIToRawKey (char c)
  846. {
  847.     UBYTE b;
  848.     SHORT r=-1;
  849.     struct MsgPort *port=0;
  850.     struct IOStdReq *req=0;
  851.     struct KeyMap *km=0;
  852.     ULONG *kmentry;
  853.     UBYTE *kmflags,*kmdkey;
  854.  
  855.     if (c>='A' && c<='Z') c+='a'-'A';
  856.  
  857.     port=CreatePort(0,0);
  858.     if (!port) goto error;
  859.     req=CreateStdIO(port);
  860.     if (!req) goto error;
  861.     km=AllocMem (sizeof(struct KeyMap),MEMF_PUBLIC | MEMF_CLEAR);
  862.     if (!km) goto error;
  863.  
  864.     if (OpenDevice("console.device",-1,req,0)) goto error;
  865.     req->io_Command=CD_ASKDEFAULTKEYMAP;
  866.     req->io_Length=sizeof(struct KeyMap);
  867.     req->io_Data=km;
  868.     DoIO(req);
  869.     if (req->io_Error) { CloseDevice (req); goto error; }
  870.  
  871.     kmentry = km->km_LoKeyMap;
  872.     kmflags = km->km_LoKeyMapTypes;
  873.  
  874.     for (r=0;r<0x40;++r,++kmentry,++kmflags) {
  875.     if (*kmflags & KCF_STRING) continue;
  876.     if (*kmflags & KCF_DEAD) {
  877.         kmdkey=(UBYTE *)(kmentry[0]);
  878.         b=InterpretDKey(kmdkey,kmdkey);
  879.         if (b==c) break;
  880.     } else if ((kmentry[0] & 0xff) == c) break;
  881.     }
  882.     if (r==0x40) {
  883.     kmentry = km->km_HiKeyMap;
  884.     kmflags = km->km_HiKeyMapTypes;
  885.     for (;r<0x68;++r,++kmentry,++kmflags) {
  886.         if (*kmflags & KCF_STRING) continue;
  887.         if (*kmflags & KCF_DEAD) {
  888.         kmdkey=(UBYTE *)(kmentry[0]);
  889.         b=InterpretDKey(kmdkey,kmdkey);
  890.         if (b==c) break;
  891.         } else if ((kmentry[0] & 0xff) == c) break;
  892.     }
  893.     }
  894.     if (r>0x67) r=-1;
  895.  
  896.     CloseDevice(req);
  897. error: if (req) DeleteStdIO (req);
  898.        if (port) DeletePort (port);
  899.        if (km) FreeMem (km,sizeof(struct KeyMap));
  900.        return (r);
  901. }
  902.  
  903. /***********************************************************/
  904. /* These are the routines that the user will call to       */
  905. /* GTRequest behavior as it is running.            */
  906. /***********************************************************/
  907.  
  908. __far BYTE GTAllocCLBit (struct GTRequest *req)
  909. {
  910.     BYTE toreturn;
  911.     for (toreturn=0;toreturn<32;++toreturn)
  912.     if (!(req->LoopBitsUsed & (1<<toreturn))) break;
  913.     if (toreturn==32) return (-1);
  914.     req->LoopBitsUsed|=(1<<toreturn);
  915.     return (toreturn);
  916. }
  917.  
  918.  
  919. __far void GTFreeCLBit (struct GTRequest *req,UBYTE bit)
  920. {
  921.     FLAGOFF(req->LoopBitsUsed,(1<<bit));
  922. }
  923.  
  924. #define FreeIntuiMsg(x) FreeMem(x,sizeof(struct IntuiMessage))
  925.  
  926. __far BOOL GTSendIntuiMsg (struct GTRequest *req,ULONG Class,ULONG Code,
  927.             USHORT Qualifier,APTR IAddress)
  928. {
  929.     struct IntuiMessage *msg;
  930.     ULONG secs,mics;
  931.  
  932.     if (!(Class & req->Window->IDCMPFlags)) return (0);
  933.  
  934.     msg=AllocMem (sizeof(struct IntuiMessage),MEMF_PUBLIC | MEMF_CLEAR);
  935.     if (!msg) return (2);
  936.  
  937.     CurrentTime(&secs,&mics);
  938.  
  939.     msg->Class=Class;
  940.     msg->Code=Code;
  941.     msg->Qualifier=Qualifier;
  942.     msg->IAddress=IAddress;
  943.     msg->Seconds=secs;
  944.     msg->Micros=mics;
  945.     msg->MouseX=req->Window->MouseX;
  946.     msg->MouseY=req->Window->MouseY;
  947.     msg->IDCMPWindow=req->Window;
  948.  
  949.     PutMsg (req->IComPort,msg);
  950.     return (0);
  951. }
  952.  
  953.  
  954.  
  955.  
  956. __far void StimulateControl (struct GTRequest *req,struct GTControl *gtc)
  957. {
  958.     if (!(gtc->Gadget->Flags & GFLG_DISABLED)) {
  959.     switch(gtc->Kind) {
  960.         case STRING_KIND:
  961.         case INTEGER_KIND:
  962.         ActivateGadget (gtc->Gadget,req->Window,0);
  963.         break;
  964.         case CHECKBOX_KIND:
  965.         SetControlAttrs(req,gtc,GTCB_Checked,
  966.             !(gtc->Gadget->Flags & GFLG_SELECTED),TAG_DONE);
  967.         break;
  968.         case CYCLE_KIND:
  969.         SetControlAttrs(req,gtc,GTCY_Active,
  970.             gtc->Attribute+1,TAG_DONE);
  971.         break;
  972.         case MX_KIND:
  973.         SetControlAttrs(req,gtc,GTMX_Active,
  974.             gtc->Attribute+1,TAG_DONE);
  975.         break;
  976.     }
  977.     }
  978. }
  979.  
  980.  
  981.  
  982.  
  983. __far void GTStimulateGadget(struct GTRequest *req,struct Gadget *g)
  984. {
  985.     struct GTControl *gtc;
  986.     gtc=FindGadgetControl (req->Controls,g);
  987.     if (gtc) StimulateControl(req,gtc);
  988. }
  989.  
  990. #define GTControlClick(r,g) GTGadgetClick(r,(g)->Gadget)
  991.  
  992. __far BOOL GTGadgetClick(struct GTRequest *req,struct Gadget *gadg)
  993. {
  994.     BOOL x=0;
  995.  
  996.     if (!(gadg->Flags & GFLG_DISABLED)) {
  997.     if (gadg->Activation & GACT_IMMEDIATE)
  998.         x|=GTSendIntuiMsg(req,IDCMP_GADGETDOWN,0,0,(APTR)gadg);
  999.     if (!((gadg->GadgetType & GTYP_GTYPEMASK)==GTYP_STRGADGET)) {
  1000.         if (gadg->Activation & GACT_RELVERIFY)
  1001.         x|=GTSendIntuiMsg(req,IDCMP_GADGETUP,0,0,(APTR)gadg);
  1002.     }
  1003.     if (x) return (x);
  1004.     GTStimulateGadget (req,gadg);
  1005.     }
  1006.     return (0);
  1007. }
  1008.  
  1009.  
  1010.  
  1011.  
  1012. __far BOOL GTKeyClick (struct GTRequest *req,UBYTE *keyinfo,UBYTE key)
  1013. {
  1014.     USHORT qual=0,rk;
  1015.     if (cismember('a',keyinfo)) qual|=0x10;
  1016.     if (cismember('A',keyinfo)) qual|=0x40;
  1017.     if (cismember('s',keyinfo)) qual|=0x01;
  1018.     if (cismember('c',keyinfo)) qual|=0x08;
  1019.  
  1020.     rk=ASCIIToRawKey(key);
  1021.     if (rk==-1) return (3);
  1022.     return (GTSendIntuiMsg(req,IDCMP_RAWKEY,rk,qual,0));
  1023. }
  1024.  
  1025.  
  1026. /*
  1027.  
  1028. __far BOOL MenuPick (struct IGRequest *req,struct IGMenu *igm)
  1029. {
  1030.     BOOL result;
  1031.     result=GTSendIntuiMsg (req,IDCMP_MENUPICK,igm->Code,0,0);
  1032.     return result;
  1033. }
  1034.  
  1035. */
  1036.  
  1037.  
  1038.  
  1039.  
  1040.  
  1041. __far void SetStringControl (struct GTRequest *req,struct GTControl *gtc,UBYTE *string)
  1042. {
  1043.     if (!((gtc->Gadget->GadgetType & GTYP_GTYPEMASK)==GTYP_STRGADGET)) return;
  1044.  
  1045.     SetControlAttrs(req,gtc,GTST_String,string,TAG_DONE);
  1046.     if (gtc->Gadget->Activation & GACT_IMMEDIATE) GTSendIntuiMsg (req,IDCMP_GADGETDOWN,0,0,gtc->Gadget);
  1047.     if (gtc->Gadget->Activation & GACT_RELVERIFY) GTSendIntuiMsg (req,IDCMP_GADGETUP,0,0,gtc->Gadget);
  1048. }
  1049.  
  1050. __far void GTSetStringGad (struct GTRequest *req,struct Gadget *gadg,UBYTE *string)
  1051. {
  1052.     struct GTControl *gtc;
  1053.     gtc=FindGadgetControl(req->Controls,gadg);
  1054.     if (gtc) SetStringControl(req,gtc,string);
  1055. }
  1056.  
  1057. __far void SetIntControl (struct GTRequest *req,struct GTControl *gtc,LONG number)
  1058. {
  1059.     if (!((gtc->Gadget->GadgetType & GTYP_GTYPEMASK)==GTYP_STRGADGET)) return;
  1060.  
  1061.     SetControlAttrs(req,gtc,GTIN_Number,number,TAG_DONE);
  1062.     if (gtc->Gadget->Activation & GACT_IMMEDIATE) GTSendIntuiMsg (req,IDCMP_GADGETDOWN,0,0,gtc->Gadget);
  1063.     if (gtc->Gadget->Activation & GACT_RELVERIFY) GTSendIntuiMsg (req,IDCMP_GADGETUP,0,0,gtc->Gadget);
  1064. }
  1065.  
  1066. __far void GTSetIntGad (struct GTRequest *req,struct Gadget *gadg,LONG number)
  1067. {
  1068.     struct GTControl *gtc;
  1069.     gtc=FindGadgetControl(req->Controls,gadg);
  1070.     if (gtc) SetIntControl(req,gtc,number);
  1071. }
  1072.  
  1073.  
  1074. /*
  1075.     BlockIGInput Function opens an blank intuition requester on top
  1076.     of an IGRequest, thereby blocking its input
  1077. */
  1078. __far void GTBlockInput(struct GTRequest *req)
  1079. {
  1080.     struct GTPrivate *id;
  1081.     struct Requester *areq;
  1082.  
  1083.     if (req && req->Window) {
  1084.     id=(struct GTPrivate *)req->InternalData;
  1085.  
  1086.     if (!(id->Blocked)) {
  1087.         if (areq=AllocMem(sizeof(struct Requester),MEMF_PUBLIC | MEMF_CLEAR)) {
  1088.         Request(areq,req->Window);
  1089.         req->Flags|=GT_INPUTBLOCKED;
  1090.         id->BlockReq=areq;
  1091.         id->Blocked=1;
  1092.         }
  1093.     } else ++id->Blocked;
  1094.     }
  1095. }
  1096.  
  1097.  
  1098.  
  1099.  
  1100.  
  1101. /*
  1102.     UnBlockIGInput closes blank requester opened by BlockIGInput, thereby
  1103.     permitting messages to come through again
  1104. */
  1105. __far void GTUnBlockInput(struct GTRequest *req)
  1106. {
  1107.     struct Requester *areq;
  1108.     struct GTPrivate *id;
  1109.  
  1110.     if (req && (req->Flags & GT_INPUTBLOCKED)) {
  1111.     id=(struct GTPrivate *)req->InternalData;
  1112.  
  1113.     --id->Blocked;
  1114.     if (!(id->Blocked)) {
  1115.         if (areq=id->BlockReq) {
  1116.         EndRequest(areq,req->Window);
  1117.         FreeMem(areq,sizeof(struct Requester));
  1118.         FLAGOFF(req->Flags,GT_INPUTBLOCKED);
  1119.         id->BlockReq=0;
  1120.         }
  1121.     }
  1122.     }
  1123. }
  1124.  
  1125.  
  1126.  
  1127.  
  1128. #define GTREQUESTIDCMP (IDCMP_GADGETUP | IDCMP_GADGETDOWN | \
  1129.             IDCMP_INTUITICKS | IDCMP_RAWKEY | IDCMP_MOUSEBUTTONS | \
  1130.             IDCMP_MOUSEMOVE | IDCMP_REFRESHWINDOW | IDCMP_MENUPICK)
  1131.  
  1132. /* You must use this instead of ModifyIDCMP!! */
  1133.  
  1134. __far void GTReqModifyIDCMP(struct GTRequest *req,ULONG IDCMP)
  1135. {
  1136.     req->AppIDCMP=IDCMP;
  1137.  
  1138.     ModifyIDCMP(req->Window,IDCMP | GTREQUESTIDCMP);
  1139. }
  1140.  
  1141.  
  1142.  
  1143.  
  1144. /***********************************************************/
  1145. /*  These routines are used by GTRequest internally.
  1146. /***********************************************************/
  1147.  
  1148. /*
  1149.     ClearWindow Function, clears inside of window to background (0)
  1150.     Used by GTRequest on exit if it doesn't close the window.
  1151. */
  1152. __far void ClearWindow (struct Window *w)
  1153. {
  1154.     SHORT x,y,X,Y;
  1155.     BYTE oldpen;
  1156.     if (!w) return ();
  1157.     x=w->BorderLeft+1;
  1158.     y=w->BorderTop+1;
  1159.     X=w->Width;
  1160.     Y=w->Height;
  1161.     X-=w->BorderRight+1;
  1162.     Y-=w->BorderBottom+1;
  1163.     oldpen=w->RPort->FgPen;
  1164.     SetAPen (w->RPort,0);
  1165.     RectFill (w->RPort,x,y,X,Y);
  1166.     SetAPen (w->RPort,oldpen);
  1167. }
  1168.  
  1169. __far void StoreGTCAttr(struct GTRequest *req,struct GTControl *gtc)
  1170. {
  1171.     UBYTE *stringbuffer=0,condition;
  1172.     ULONG t,*tp;
  1173.  
  1174.     if (req->Flags & STOREDATA) {
  1175.     if (gtc->Flags & STOREDATA) {
  1176.         UBYTE *data;
  1177.  
  1178.         data=req->DataStruct;
  1179.         data+=gtc->FieldOffset;
  1180.  
  1181.         if ((gtc->Gadget->GadgetType & GTYP_GTYPEMASK)==GTYP_STRGADGET) {
  1182.         struct StringInfo *si;
  1183.         si=(struct StringInfo *)gtc->Gadget->SpecialInfo;
  1184.         stringbuffer=si->Buffer;
  1185.         }
  1186.  
  1187.         if (gtc->SetDataFromGadget) (*(gtc->SetDataFromGadget)) (req,gtc,data);
  1188.         else {
  1189.         condition=stringbuffer && ISFLAGOFF(gtc->Flags,GTC_ATTROVERRIDESSTRING);
  1190.         switch (gtc->FieldType) {
  1191.             case FLD_SHORT: {
  1192.             SHORT *sp;
  1193.             sp=(BYTE *)data;
  1194.             *sp= condition ? atol(stringbuffer) : gtc->Attribute;
  1195.             }
  1196.             break;
  1197.             case FLD_BYTE: {
  1198.             BYTE *bp;
  1199.             bp=(BYTE *)data;
  1200.             *bp= condition ? atol(stringbuffer) : gtc->Attribute;
  1201.             }
  1202.             break;
  1203.             case FLD_FLOAT: {
  1204.             GTFLOAT *f;
  1205.             f=(GTFLOAT *)data;
  1206.             if (condition) {
  1207.                 *f=(GTFLOAT)StringToFloat(stringbuffer);
  1208.                 break;
  1209.             }
  1210.             }
  1211.             case FLD_POINTER:
  1212.             case FLD_LONG:
  1213.             case FLD_STRINGPTR: {
  1214.             ULONG *lp;
  1215.             lp=(ULONG *)data;
  1216.             *lp= condition && gtc->FieldType==FLD_LONG ?
  1217.                 atol(stringbuffer) : gtc->Attribute;
  1218.             }
  1219.             break;
  1220.             case FLD_STRINGINSTRUCT: {
  1221.             UBYTE *s;
  1222.             s= condition ? stringbuffer : (UBYTE *)gtc->Attribute;
  1223.             strncpy(data,s,gtc->FieldSize);
  1224.             }
  1225.             break;
  1226.             case FLD_STRINGPOINTEDTOINSTRUCT: {
  1227.             UBYTE **p,*x,*s;
  1228.             p=(UBYTE **)data;
  1229.             x=*p;
  1230.             s= condition ? stringbuffer : (UBYTE *)gtc->Attribute;
  1231.             strncpy(x,s,gtc->FieldSize);
  1232.             }
  1233.             break;
  1234.             case FLD_BOOLBIT: {
  1235.             ULONG *lp;
  1236.             lp=(ULONG *)data;
  1237.  
  1238.             SETFLAG(*lp,1<<gtc->FieldBit,gtc->Attribute);
  1239.             }
  1240.             break;
  1241.             case FLD_ATTRBIT: {
  1242.             ULONG *lp;
  1243.             lp=(ULONG *)data;
  1244.             *lp=1<<gtc->Attribute;
  1245.             }
  1246.             break;
  1247.             case FLD_ORATTR: {
  1248.             ULONG *lp;
  1249.             lp=(ULONG *)data;
  1250.             *lp|=gtc->Attribute;
  1251.             }
  1252.             break;
  1253.             case FLD_ORATTRBIT: {
  1254.             ULONG *lp;
  1255.             lp=(ULONG *)data;
  1256.             *lp|=1<<gtc->Attribute;
  1257.             }
  1258.             break;
  1259.         }
  1260.         }
  1261.     }
  1262.     }
  1263. }
  1264.  
  1265. __far void InitGTCAttr(struct GTRequest *req,struct GTControl *gtc)
  1266. {
  1267.     BYTE f=0;
  1268.  
  1269.  
  1270.     if (!stricmp(gtc->NewGadget->ng_GadgetText,"Ind. W/H:")) f=1;
  1271.     if (req->Flags & INITFROMDATA) {
  1272.     if (gtc->Flags & INITFROMDATA) {
  1273.         UBYTE *data;
  1274.  
  1275.         data=req->DataStruct;
  1276.         data+=gtc->FieldOffset;
  1277.  
  1278.         if (gtc->SetGadgetFromData) (*(gtc->SetGadgetFromData)) (req,gtc,data);
  1279.         else {
  1280.         switch (gtc->FieldType) {
  1281.             case FLD_SHORT: {
  1282.             SHORT *sp;
  1283.             sp=(BYTE *)data;
  1284.             SetControlAttrs(req,gtc,gtc->AttributeTag,*sp,TAG_DONE);
  1285.             gtc->Attribute=*sp;
  1286.             }
  1287.             break;
  1288.             case FLD_BYTE: {
  1289.             BYTE *bp;
  1290.             bp=(BYTE *)data;
  1291.             SetControlAttrs(req,gtc,gtc->AttributeTag,*bp,TAG_DONE);
  1292.             gtc->Attribute=*bp;
  1293.             }
  1294.             break;
  1295.             case FLD_FLOAT: {
  1296.             UBYTE buf[30];
  1297.             GTFLOAT *fp;
  1298.             fp=(GTFLOAT *)data;
  1299.             FloatToString(*fp,buf);
  1300.             SetControlAttrs(req,gtc,gtc->AttributeTag,buf,TAG_DONE);
  1301.             gtc->Attribute=(ULONG)*fp;
  1302.             }
  1303.             break;
  1304.             case FLD_POINTER:
  1305.             case FLD_LONG:
  1306.             case FLD_STRINGPOINTEDTOINSTRUCT:
  1307.             case FLD_STRINGPTR: {
  1308.             ULONG *lp;
  1309.             lp=(ULONG *)data;
  1310.             SetControlAttrs(req,gtc,gtc->AttributeTag,*lp,TAG_DONE);
  1311.             gtc->Attribute=*lp;
  1312.             }
  1313.             break;
  1314.             case FLD_STRINGINSTRUCT:
  1315.             SetControlAttrs(req,gtc,gtc->AttributeTag,data,TAG_DONE);
  1316.             break;
  1317.             case FLD_BOOLBIT: {
  1318.             ULONG *lp,x;
  1319.             lp=(ULONG *)data;
  1320.             x=ISFLAGON(*lp,1<<gtc->FieldBit) ? 1 : 0;
  1321.             SetControlAttrs(req,gtc,gtc->AttributeTag,x,TAG_DONE);
  1322.             gtc->Attribute=x;
  1323.             }
  1324.             break;
  1325.             case FLD_ATTRBIT: {
  1326.             ULONG *lp,n,c;
  1327.             lp=(ULONG *)data;
  1328.             c=*lp;
  1329.             if (c) for (n=1;n<32 && c!=1;++n,c>>=1);
  1330.             else n=0;
  1331.             if (n!=32) {
  1332.                 SetControlAttrs(req,gtc,gtc->AttributeTag,n,TAG_DONE);
  1333.                 gtc->Attribute=n;
  1334.             }
  1335.             }
  1336.             break;
  1337.             /* If more than one bit is set, nothing happens!! */
  1338.  
  1339.             /* break; */
  1340.             /* Not necessary for last case */
  1341.         }
  1342.         }
  1343.     }
  1344.     }
  1345. }
  1346.  
  1347. __far struct GTPKind *FindGTPKClassInList(UBYTE *Name,struct GTPKind *list)
  1348. {
  1349.     for (;list && list->Name;list++)
  1350.     if (!strcmp(list->Name,Name)) return list;
  1351.     return 0;
  1352. }
  1353.  
  1354. __far struct GTPKind *FindGTPKClass(struct GTRequest *req,UBYTE *Name)
  1355. {
  1356.     struct GTPKind *gc;
  1357.     if (gc=FindGTPKClassInList(Name,req->LocalPKindClassList)) return gc;
  1358.     return FindGTPKClassInList(Name,GlobalPKindClassList);
  1359. }
  1360.  
  1361. __far struct MessageClass *FindMsgClassInList (UBYTE *Name,struct MessageClass *list)
  1362. {
  1363.     for (;list && list->Name;list++)
  1364.     if (!strcmp(list->Name,Name)) return list;
  1365.     return 0;
  1366. }
  1367.  
  1368. __far struct MessageClass *FindMsgClass(struct GTRequest *req,UBYTE *Name)
  1369. {
  1370.     struct MessageClass *mc;
  1371.  
  1372.     if (mc=FindMsgClassInList(Name,req->LocalMsgClassList)) return mc;
  1373.     return FindMsgClassInList(Name,GlobalMsgClassList);
  1374. }
  1375.  
  1376. __far void BindClassToMsgHandler(struct GTRequest *req,struct MessageHandler *mh)
  1377. {
  1378.     if (!(mh->IsType) && mh->Name) {
  1379.     struct MessageClass *mc;
  1380.  
  1381.     mc=FindMsgClass(req,mh->Name);
  1382.     if (mc) {
  1383.         mh->IsType=mc->IsType;
  1384.     }
  1385.     }
  1386. }
  1387.  
  1388. __far void ProcessMsgHandler (struct GTRequest *req,struct MessageHandler *mh,
  1389.             struct IntuiMessage *msg,struct GTControl *gtc)
  1390. {
  1391.  
  1392.     if (mh->IsType) {
  1393.     if ((*(mh->IsType)) (req,msg,gtc,mh)) {
  1394.         if (mh->HandlerFunction) {
  1395.         (*(mh->HandlerFunction)) (req,msg,gtc,mh);
  1396.         }
  1397.     }
  1398.     }
  1399. }
  1400.  
  1401. extern struct Library *GadToolsBase;
  1402.  
  1403. struct Gadget *ControlToGadget(struct GTRequest *req,struct Gadget *gad,
  1404.                    struct GTControl *gtc,struct VisualInfo *vinfo)
  1405. {
  1406.    if (!(gtc->Flags & GTC_INTERNALCONTROLIGNORE)) {
  1407.     if (gtc->Flags & GTC_PSEUDOKIND) {
  1408.         struct GTPKind *gc;
  1409.         if (gc=FindGTPKClass(req,(UBYTE *)gtc->Kind)) {
  1410.         if (gc->Create)
  1411.             gtc->Gadget=gad=(*(gc->Create)) (gc,gad,gtc,req,vinfo);
  1412.         }
  1413.     } else {
  1414.         gtc->NewGadget->ng_VisualInfo=vinfo;
  1415.         gtc->Gadget=gad=CreateGadgetA(gtc->Kind,gad,gtc->NewGadget,gtc->GadgetTags);
  1416.         if(gad && (gtc->Kind==STRING_KIND || gtc->Kind==INTEGER_KIND)) {
  1417.         if (GadToolsBase->lib_Version==37)
  1418.             gad->Activation|=GACT_IMMEDIATE;
  1419.         }
  1420.         /* ALL string and integer gadgets
  1421.         should have GACT_IMMEDIATE set
  1422.         if you want the verify functions
  1423.         or DSelect functions to work.
  1424.         This flag is only directly set
  1425.         under v37 to conform to RKM.
  1426.         Applications should set it
  1427.         in their taglists!
  1428.         */
  1429.     }
  1430.     }
  1431.     return gad;
  1432. }
  1433.  
  1434. struct Menu *GTInitMenus(struct GTRequest *req,struct VisualInfo *vinfo)
  1435. {
  1436.     struct Menu *MenuStrip;
  1437.  
  1438.     if (MenuStrip=CreateMenus(req->Menus,TAG_DONE)) {
  1439.     if (LayoutMenus(MenuStrip,vinfo,TAG_DONE)) {
  1440.         if (SetMenuStrip(req->Window,MenuStrip)) {
  1441.         return MenuStrip;
  1442.         }
  1443.     }
  1444.     FreeMenus(MenuStrip);
  1445.     }
  1446.     return 0;
  1447. }
  1448.  
  1449. void InitReqSet(struct GTReqSet *rs)
  1450. {
  1451.     rs->MsgPort=0;
  1452.     NewList(&rs->List);
  1453. }
  1454.  
  1455. void EndAllRequests(struct GTReqSet *rs,LONG terminate,struct MessageHandler *mh,
  1456.                struct GTControl *gtc)
  1457. {
  1458.     struct ReqNode *rn;
  1459.  
  1460.     for (rn=FirstItem(&rs->List);rn;rn=NextItem(rn)) {
  1461.     EndGTRequest(rn->req,terminate,mh,gtc);
  1462.     }
  1463. }
  1464.  
  1465. void StripIntuiMessages(struct MsgPort *mp,struct Window *win)
  1466. {
  1467.     struct IntuiMessage *msg;
  1468.     struct Node *succ;
  1469.  
  1470.     msg=(struct IntuiMessage *)mp->mp_MsgList.lh_Head;
  1471.  
  1472.     while (succ = msg->ExecMessage.mn_Node.ln_Succ)
  1473.     {
  1474.     if (msg->IDCMPWindow == win) {
  1475.         Remove(msg);
  1476.         if (msg->ExecMessage.mn_ReplyPort)
  1477.         ReplyMsg(msg);
  1478.         else FreeIntuiMsg(msg);
  1479.     }
  1480.     msg=(struct IntuiMessage *)succ;
  1481.     }
  1482. }
  1483.  
  1484. void DetachUserPort(struct Window *win)
  1485. {
  1486.     Forbid();
  1487.  
  1488.     StripIntuiMessages(win->UserPort,win);
  1489.     win->UserPort=0;
  1490.     ModifyIDCMP(win,0);
  1491.  
  1492.     Permit();
  1493. }
  1494.  
  1495. /* req Must be part of a set when this is called. */
  1496. __far void FreeRequest(struct GTReqSet *rs, struct GTRequest *req)
  1497. {
  1498.     struct GTPrivate *priv;
  1499.     struct GTControl *prev=0,*gtc;
  1500.     UBYTE flag=1;
  1501.  
  1502.     priv=(struct GTPrivate *)req->InternalData;
  1503.  
  1504.     if (!priv) return;
  1505.  
  1506.     if (priv->MenuStrip) {
  1507.     ClearMenuStrip(req->Window);
  1508.     FreeMenus(priv->MenuStrip);
  1509.     }
  1510.  
  1511.     if (req->Flags & GT_GADGETSADDED)
  1512.     RemoveGList(req->Window,priv->Context,-1);
  1513.  
  1514.     if (priv->Context) {
  1515.     for (gtc=req->Controls;gtc;gtc=gtc->Next) {
  1516.         if (flag) {
  1517.         if (!(gtc->Flags & GTC_INTERNALCONTROLIGNORE)) {
  1518.             if (gtc->Gadget) {
  1519.             if (gtc->Flags & GTC_PSEUDOKIND) {
  1520.                 struct GTPKind *gc;
  1521.                 if(gc=FindGTPKClass(req,(UBYTE *)gtc->Kind)) {
  1522.                 if (gc->Destroy)
  1523.                     (*(gc->Destroy)) (gc,gtc,req);
  1524.                 }
  1525.             }
  1526.             } else flag=0;
  1527.         }
  1528.         }
  1529.         if (gtc->Flags & (GTC_INTERNALCONTROL | GTC_INTERNALCONTROLIGNORE)) {
  1530.         if (prev) prev->Next=gtc->Next;
  1531.         } else prev=gtc;
  1532.     }
  1533.     if (!prev) req->Controls=0;
  1534.  
  1535.     FreeGadgets(priv->Context);
  1536.     }
  1537.  
  1538.     if (priv->vinfo) FreeVisualInfo(priv->vinfo);
  1539.  
  1540.     {
  1541.     USHORT i;
  1542.     struct ReqNode *rn;
  1543.  
  1544.     for (rn=FirstItem(&rs->List),i=0;rn;rn=NextItem(rn),++i);
  1545.  
  1546.     if (priv->OpenedWindow) {
  1547.         if (i!=1) DetachUserPort(req->Window);
  1548.         else rs->MsgPort=0;
  1549.         req->Window=0;
  1550.         CloseWindow(priv->OpenedWindow);
  1551.     } else {
  1552.         ClearWindow(req->Window);
  1553.         if (i==1) rs->MsgPort=0;
  1554.         else {
  1555.         DetachUserPort(req->Window);
  1556.         ModifyIDCMP(req->Window,req->AppIDCMP);
  1557.         }
  1558.     }
  1559.     }
  1560.  
  1561.     {
  1562.     struct IntuiText *t;
  1563.     struct Border *b;
  1564.     struct Image *i;
  1565.  
  1566.     for (t=req->ITexts;t;t=t->NextText)
  1567.         t->TopEdge-=priv->YOffSet;
  1568.     for (b=req->Borders;b;b=b->NextBorder)
  1569.         b->TopEdge-=priv->YOffSet;
  1570.     for (i=req->Images;i;i=i->NextImage)
  1571.         i->TopEdge-=priv->YOffSet;
  1572.  
  1573.     for (gtc=req->Controls;gtc;gtc=gtc->Next)
  1574.         if (gtc->NewGadget) gtc->NewGadget->ng_TopEdge-=priv->YOffSet;
  1575.     }
  1576.  
  1577.  
  1578.     FreeRemember(&req->GTKey,1);
  1579.     req->InternalData=0;
  1580. }
  1581.  
  1582. /* req must be part of rs before initialized */
  1583. __far LONG InitShowRequest(struct GTReqSet *rs,struct GTRequest *req)
  1584. {
  1585.     struct Gadget *gad;
  1586.     struct GTControl *gtc;
  1587.     struct GTPrivate *priv;
  1588.  
  1589.     req->GTKey=0;
  1590.  
  1591.     if (priv=AllocRemember(&req->GTKey,sizeof(*priv),MEMF_PUBLIC | MEMF_CLEAR)) {
  1592.  
  1593.     req->InternalData=(APTR)priv;
  1594.  
  1595.     /* Note that "binding" classes to handlers only happens when GTRequest
  1596.         is first called.  This means that you can't add unbound message
  1597.         handler structures (with IsType==0) while GTRequest is running.
  1598.         You can however bind an unbound message handler structure using
  1599.         BindClassToMsgHandler as per below and then add that bound MsgHandler.
  1600.     */
  1601.  
  1602.     priv->Context=0;
  1603.     priv->OpenedWindow=0;
  1604.     priv->YOffSet=0;
  1605.  
  1606.     FLAGOFF(req->Flags,GT_GADGETSADDED);
  1607.  
  1608.     {
  1609.         struct MessageHandler *mh;
  1610.  
  1611.         for (gtc=req->Controls;gtc;gtc=gtc->Next) {
  1612.         for (mh=gtc->MsgHandlerList;mh;mh=mh->Next)
  1613.             BindClassToMsgHandler(req,mh);
  1614.         }
  1615.  
  1616.         for (mh=req->MsgHandlerList;mh;mh=mh->Next)
  1617.         BindClassToMsgHandler(req,mh);
  1618.     }
  1619.  
  1620.     req->Terminate=0;
  1621.     req->ActiveControl=0;
  1622.  
  1623.     for (gtc=req->Controls;gtc;gtc=gtc->Next) {
  1624.         if (!(gtc->Flags & GTC_GOTRAWKEY) && gtc->ASCIICommand) {
  1625.         gtc->RawKeyCommand=ASCIIToRawKey(gtc->ASCIICommand);
  1626.         gtc->Flags |= GTC_GOTRAWKEY;
  1627.         }
  1628.         gtc->Gadget=0;
  1629.     }
  1630.  
  1631.     if (req->Window ||
  1632.       (priv->OpenedWindow=req->Window=OpenWindowTagList(NULL,req->NewWindowTags))) {
  1633.  
  1634.         req->AppIDCMP=req->Window->IDCMPFlags;
  1635.  
  1636.         if (rs->MsgPort) {
  1637.         ModifyIDCMP(req->Window,0);
  1638.         req->Window->UserPort=rs->MsgPort;
  1639.         ModifyIDCMP(req->Window,req->AppIDCMP | GTREQUESTIDCMP);
  1640.         } else {
  1641.         ModifyIDCMP(req->Window,req->AppIDCMP | GTREQUESTIDCMP);
  1642.         rs->MsgPort=req->Window->UserPort;
  1643.         }
  1644.  
  1645.         {
  1646.         struct Screen *s;
  1647.         struct IntuiText *t;
  1648.         struct Border *b;
  1649.         struct Image *i;
  1650.  
  1651.         s=req->Window->WScreen;
  1652.         priv->YOffSet=s->WBorTop + s->Font->ta_YSize - 9;
  1653.  
  1654.         for (t=req->ITexts;t;t=t->NextText)
  1655.             t->TopEdge+=priv->YOffSet;
  1656.         for (b=req->Borders;b;b=b->NextBorder)
  1657.             b->TopEdge+=priv->YOffSet;
  1658.         for (i=req->Images;i;i=i->NextImage)
  1659.             i->TopEdge+=priv->YOffSet;
  1660.  
  1661.         for (gtc=req->Controls;gtc;gtc=gtc->Next)
  1662.             if (gtc->NewGadget) gtc->NewGadget->ng_TopEdge+=priv->YOffSet;
  1663.         }
  1664.  
  1665.  
  1666.  
  1667.         if (req->ITexts) PrintIText(req->Window->RPort,req->ITexts,0,0);
  1668.         if (req->Borders) DrawBorder(req->Window->RPort,req->Borders,0,0);
  1669.         if (req->Images) DrawImage(req->Window->RPort,req->Images,0,0);
  1670.  
  1671.         if (priv->vinfo=GetVisualInfo(req->Window->WScreen,TAG_DONE)) {
  1672.         gtc=0;
  1673.         if (gad=CreateContext(&priv->Context)) {
  1674.             struct Gadget *lasttime;
  1675.  
  1676.             do {
  1677.             struct TagItem *tia,*nti;
  1678.  
  1679.             lasttime=gad;
  1680.             for (gtc=req->Controls;gtc;gtc=gtc->Next) {
  1681.                 if (!(gtc->Gadget)) {
  1682.                 nti=0;
  1683.  
  1684.                 if (tia=FindTagItem(GTCT_NEXTDATATOGADGETADDRESS,
  1685.                  gtc->GadgetTags)) {
  1686.                     struct GTControl *gtc2;
  1687.  
  1688.                     tia++;
  1689.                     gtc2=(struct GTControl *)tia->ti_Data;
  1690.                     if (gtc2->Gadget) {
  1691.                     if (nti=CloneTagItems(gtc->GadgetTags)) {
  1692.                         tia=FindTagItem(GTCT_NEXTDATATOGADGETADDRESS,nti);
  1693.                         tia->ti_Tag=TAG_IGNORE;
  1694.                         ++tia;
  1695.                         tia->ti_Data=gtc2->Gadget;
  1696.                         tia=gtc->GadgetTags;
  1697.                         gtc->GadgetTags=nti;
  1698.                     }
  1699.                     } else continue;
  1700.                 }
  1701.                 gad=ControlToGadget(req,gad,gtc,priv->vinfo);
  1702.                 if (nti) {
  1703.                     gtc->GadgetTags=tia;
  1704.                     FreeTagItems(nti);
  1705.                 }
  1706.                 if (!gad) break;
  1707.                 }
  1708.             }
  1709.             } while (lasttime!=gad && gad);
  1710.             if (gad) {
  1711.             if (req->Menus) priv->MenuStrip=GTInitMenus(req,priv->vinfo);
  1712.  
  1713.             if (!(req->Menus) || priv->MenuStrip) {
  1714.                 req->LastGadgetEvent=&priv->LastGadgetEvent;
  1715.                 req->BeforeLastGadgetEvent=&priv->BeforeLastGadgetEvent;
  1716.  
  1717.                 AddGList(req->Window,priv->Context,-1,-1,0);
  1718.                 RefreshGList(priv->Context,req->Window,0,-1);
  1719.                 GT_RefreshWindow(req->Window,NULL);
  1720.  
  1721.                 req->Flags |= GT_GADGETSADDED;
  1722.  
  1723.                 if (req->Flags & INITFROMDATA) {
  1724.                 for (gtc=req->Controls;gtc;gtc=gtc->Next)
  1725.                     InitGTCAttr(req,gtc);
  1726.                 }
  1727.  
  1728.                 if (req->InitFunction) (*(req->InitFunction)) (req);
  1729.  
  1730.                 return 1;
  1731.             }
  1732.             }
  1733.         }
  1734.         }
  1735.     }
  1736.     FreeRequest (rs,req);
  1737.  
  1738.     }
  1739.     return 0;
  1740. }
  1741.  
  1742. LONG AddGTRequest(struct GTReqSet *rs,struct GTRequest *gtr)
  1743. {
  1744.     struct ReqNode *rn;
  1745.  
  1746.     if (rn=AllocMem(sizeof(*rn),MEMF_PUBLIC | MEMF_CLEAR)) {
  1747.     rn->req=gtr;
  1748.     AddTail(&rs->List,rn);
  1749.  
  1750.     if (InitShowRequest(rs,gtr))
  1751.         return 1;
  1752.  
  1753.     Remove(rn);
  1754.     FreeMem(rn,sizeof(*rn));
  1755.     }
  1756.     return 0;
  1757. }
  1758.  
  1759. __far void ProcessReqSet (struct GTReqSet *set)
  1760. {
  1761.     struct GTControl *gtc;
  1762.     UBYTE cont;
  1763.     struct IntuiMessage Msg,*pMsg;
  1764.     ULONG Signals=0;
  1765.     struct ReqNode *rn,*nextrn;
  1766.     struct GTRequest *req;
  1767.     struct GTPrivate *priv;
  1768.  
  1769.     while (FirstItem(&set->List)) {
  1770.  
  1771.     for (rn=FirstItem(&set->List);rn;rn=nextrn) {
  1772.         nextrn=NextItem(rn);
  1773.         if (rn->req->Terminate) {
  1774.         if (req->Flags & STOREDATA && req->Terminate>0) {
  1775.             for (gtc=req->Controls;gtc;gtc=gtc->Next)
  1776.             StoreGTCAttr(req,gtc);
  1777.         }
  1778.         FreeRequest(set,req);
  1779.         Remove(rn);
  1780.         FreeMem(rn,sizeof(*rn));
  1781.         }
  1782.     }
  1783.     if (!FirstItem(&set->List)) break;
  1784.  
  1785.     Signals|=SetSignal(0,0);
  1786.     cont=0;
  1787.  
  1788.     pMsg=GT_GetIMsg(set->MsgPort);
  1789.  
  1790.     if (!pMsg) {
  1791.         for (rn=FirstItem(&set->List);rn;rn=NextItem(rn)) {
  1792.         if (rn->req->SignalFunction)
  1793.             cont=(*(rn->req->SignalFunction)) (rn->req,Signals) ? 1 : cont;
  1794.         }
  1795.     }
  1796.  
  1797.     if (!cont && !pMsg) {
  1798.         for (rn=FirstItem(&set->List);rn;rn=NextItem(rn)) {
  1799.         if (rn->req->CallLoop) {
  1800.             if (rn->req->LoopFunction) {
  1801.             (*(rn->req->LoopFunction)) (req);
  1802.             cont=1;
  1803.             }
  1804.         }
  1805.         }
  1806.     }
  1807.  
  1808.     if (cont) continue;
  1809.     if (!pMsg) {
  1810.         ULONG WaitSignals;
  1811.  
  1812.         WaitSignals=1<<set->MsgPort->mp_SigBit;
  1813.  
  1814.         for (rn=FirstItem(&set->List);rn;rn=NextItem(rn))
  1815.         WaitSignals|=rn->req->AdditionalSignals;
  1816.  
  1817.         Signals=Wait(WaitSignals);
  1818.         continue;
  1819.     }
  1820.     if (pMsg) {
  1821.         Msg=*pMsg;
  1822.         if (pMsg->ExecMessage.mn_ReplyPort)
  1823.         GT_ReplyIMsg(pMsg);
  1824.         else FreeIntuiMsg(pMsg);
  1825.         pMsg=0;
  1826.     }
  1827.  
  1828.     for (rn=FirstItem(&set->List);rn;rn=NextItem(rn))
  1829.         if (rn->req->Window==Msg.IDCMPWindow) break;
  1830.  
  1831.     if (rn) req=rn->req;
  1832.     else continue;
  1833.  
  1834.     priv=(struct GTPrivate *)req->InternalData;
  1835.  
  1836.     /* Process Message Now */
  1837.  
  1838.     if (Msg.Class==IDCMP_RAWKEY) {
  1839.         BOOL Processed=0;
  1840.  
  1841.         for (gtc=req->Controls;gtc;gtc=gtc->Next) {
  1842.         if (gtc->HandleKeyCommand)
  1843.             Processed=(*(gtc->HandleKeyCommand)) (req,gtc,&Msg);
  1844.         else if (gtc->ASCIICommand) {
  1845.             USHORT rq=0;
  1846.             if (Msg.Qualifier & 7) rq=1;  /* shift */
  1847.             if (Msg.Qualifier & 8) rq|=8; /* control */
  1848.             if (Msg.Qualifier & 0x30) rq|=0x10; /* alt */
  1849.             if (Msg.Qualifier & 0xc0) rq|=0x40; /* command (Amiga) */
  1850.             if (gtc->RawKeyCommand==Msg.Code
  1851.              && gtc->Qualifier==rq) {
  1852.             GTControlClick(req,gtc);
  1853.             Processed=1;
  1854.             }
  1855.         }
  1856.         if (Processed) break;
  1857.         }
  1858.         if (Processed) continue;
  1859.     }
  1860.  
  1861.  
  1862.     if (Msg.Class & req->AppIDCMP) {
  1863.         struct MessageHandler *mh;
  1864.  
  1865.         for (mh=req->MsgHandlerList;mh;mh=mh->Next)
  1866.         ProcessMsgHandler (req,mh,&Msg,0);
  1867.  
  1868.         for (gtc=req->Controls;gtc;gtc=gtc->Next) {
  1869.         for (mh=gtc->MsgHandlerList;mh;mh=mh->Next)
  1870.             ProcessMsgHandler(req,mh,&Msg,gtc);
  1871.         }
  1872.         if (Msg.Class & IDCMP_MENUPICK && req->MenuInfo) {
  1873.         struct GTMenuInfo *menus;
  1874.  
  1875.         for (menus=req->MenuInfo;menus->Code;++menus)
  1876.             if (menus->Code==Msg.Code) {
  1877.             if (menus->Function)
  1878.                 (*(menus->Function)) (req,&Msg);
  1879.             break;
  1880.             }
  1881.         }
  1882.     }
  1883.  
  1884.     if (Msg.Class==IDCMP_GADGETUP ||
  1885.      Msg.Class==IDCMP_GADGETDOWN) {
  1886.         if (gtc=FindGadgetControl(req->Controls,Msg.IAddress)) {
  1887.  
  1888.         if (Msg.Class==IDCMP_GADGETDOWN) {
  1889.             if (gtc->GDownUpdateControl!=0xffffffff) {
  1890.             if (gtc->GDownUpdateControl)
  1891.                 (*(gtc->GDownUpdateControl)) (req,gtc,&Msg);
  1892.             else DispatchDefSetControlAttr(req,gtc,&Msg);
  1893.             }
  1894.             if (!((gtc->Gadget->GadgetType
  1895.              & GTYP_GTYPEMASK)==GTYP_STRGADGET))
  1896.             req->ActiveControl=gtc;
  1897.             else req->ActiveControl=0;
  1898.         } else {
  1899.             if (gtc->GUpUpdateControl!=0xffffffff) {
  1900.             if (gtc->GUpUpdateControl)
  1901.                 (*(gtc->GUpUpdateControl)) (req,gtc,&Msg);
  1902.             else DispatchDefSetControlAttr(req,gtc,&Msg);
  1903.             }
  1904.             req->ActiveControl=0;
  1905.         }
  1906.         }
  1907.  
  1908.         if (Msg.Class==IDCMP_GADGETUP) {
  1909.         struct Gadget *g;
  1910.         g=(struct Gadget *)Msg.IAddress;
  1911.         if (g && (g->GadgetType
  1912.          & GTYP_GTYPEMASK)==GTYP_STRGADGET) {
  1913.             g=g->NextGadget;
  1914.             if (g && (g->GadgetType
  1915.              & GTYP_GTYPEMASK)==GTYP_STRGADGET) {
  1916.             ActivateGadget(g,req->Window,0);
  1917.             }
  1918.         }
  1919.  
  1920.         }
  1921.         priv->BeforeLastGadgetEvent=priv->LastGadgetEvent;
  1922.         priv->LastGadgetEvent=Msg;
  1923.     }
  1924.  
  1925.     }
  1926. }
  1927.  
  1928. __far LONG GTRequest(struct GTRequest *req)
  1929. {
  1930.     LONG retval;
  1931.     struct GTReqSet rs;
  1932.  
  1933.     InitReqSet(&rs);
  1934.  
  1935.     if (retval=AddGTRequest(&rs,req)) {
  1936.     ProcessReqSet (&rs);
  1937.  
  1938.     retval=req->Terminate;
  1939.     }
  1940.     return retval;
  1941. }
  1942.  
  1943. struct GTControl *DuplicateControl(struct Remember **key,struct GTControl *c)
  1944. {
  1945.     struct GTControl *d;
  1946.  
  1947.     if (d=AllocRemember(key,sizeof(*d),MEMF_PUBLIC)) {
  1948.     *d=*c;
  1949.     }
  1950.     return d;
  1951. }
  1952.  
  1953. struct GTControl *DuplicateControlList(struct Remember **key,struct GTControl *c)
  1954. {
  1955.     struct GTControl *p,*d,*h=0;
  1956.  
  1957.     p=0;
  1958.  
  1959.     while (c) {
  1960.     if (d=DuplicateControl(key,c)) {
  1961.         if (p) {
  1962.         p->Next=d;
  1963.         } else h=d;
  1964.         p=d;
  1965.     } else { h=0; break; }
  1966.     c=c->Next;
  1967.     }
  1968.  
  1969.     return h;
  1970. }
  1971.  
  1972.  
  1973. struct Request *DuplicateRequest (struct Remember **key,struct GTRequest *req)
  1974. {
  1975.     struct GTRequest *dreq;
  1976.  
  1977.     if (key) {
  1978.     if (dreq=AllocRemember(key,sizeof(*dreq),MEMF_PUBLIC)) {
  1979.         *dreq=*req;
  1980.  
  1981.         if (dreq->Controls=DuplicateControlList(key,req->Controls)) {
  1982.         return dreq;
  1983.         }
  1984.  
  1985.     }
  1986.     }
  1987.     return 0;
  1988. }
  1989.  
  1990.  
  1991.